﻿using ScFramework.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VolumetricLines;

public class FuncManager : LogicModuleBase<InputManager>
{
    Player player;
    public override void OnEnable()
    {
        base.OnEnable();
        player = GetInnerModule<InstanceInfo>().Player;
    }
    public Frame frames = null;
    void SetLayer()
    {
        foreach (var x in GetInnerModule<InstanceInfo>().MapDic)
        {
            if (x.Key.Type == player.TriData.Type)
            {
                x.Value.gameObject.layer = LayerMask.NameToLayer("ActiveGround");

            }
            else
            {
                x.Value.gameObject.layer = LayerMask.NameToLayer("Ground");
            }
        }

    }
    void OnNotFree()
    {

            Debug.Assert(player.TriData.IsAntiClock());
        if (InputManager.Instance.GetButtonDown("Jump"))
        {
            player.DownDir = player.TriData.GetDownVtr(player.TriData.GetId(player.DownDir) + 1);
        }
        if (InputManager.Instance.GetButtonDown("Left"))
        {
                ChangePlayerTo(player.TriData.GetLine(player.TriData.GetId(player.DownDir) + 2));

        }
        if (InputManager.Instance.GetButtonDown("Right"))
        {
            ChangePlayerTo(player.TriData.GetLine(player.TriData.GetId(player.DownDir) + 1));
        }
        if (InputManager.Instance.GetKeyDown(KeyCode.Mouse0))
        {
            var ray = Camera.main.ScreenPointToRay(InputManager.Instance.MousePosition);

            var hit = Physics2D.RaycastAll(new Vector2(ray.origin.x, ray.origin.y), Vector2.zero, Mathf.Infinity);
            Debug.Log(hit.Length);
            if ((hit ).Length > 0)
            {
                foreach (var x in hit)
                {
                    if (x.transform.GetComponent<MeshComp>() is MeshComp c)
                    {
                        if(c.Tri.ContainLine(player.TriData.GetLine(0))&& c.Tri.ContainLine(player.TriData.GetLine(1)))
                        {
                            break;
                        }
                        for(int i = 0; i < 3; i++)
                        {
                            if (c.Tri.ContainLine(player.TriData.GetLine(i))){
                                player.ToTri(c.Tri);
                                break;
                            }
                        }
                        break;
                    }
                }
            }
        }
        if (frames == null)
        {
            frames =  ResourceManager.Instance.Instantiate("Prefabs/Frame").GetComponent<Frame>();

        }
        var ps = player.TriData.Points.ConvertAll(s => (Vector2)s);
        frames.SetPoint(ps,player.Scale);
        frames.gameObject.SetActive(true);
        if (InputManager.Instance.GetButton("Interact"))
        {
            player.ToFree();
            frames.gameObject.SetActive(false);
            SetLayer();
        }
    }
    void ChangePlayerTo(Tuple<Vector2,Vector2> v)
    {
        List<TriData> tp = new List<TriData>();
        foreach(var x in GetInnerModule<InstanceInfo>().MapDic)
        {
            if (x.Key.ContainLine(v))
            {
                tp.Add(x.Key);
            }
        }
        Debug.Assert(tp.Count > 0 && tp.Count < 3);
        if (tp.Count > 1)
        {
            if (tp[0].ContainLine(player.TriData.GetLine(0)) && tp[0].ContainLine(player.TriData.GetLine(1)))
            {
                player.ToTri(tp[1],tp[1].GetLineId(v));
            }
            else player.ToTri(tp[0],tp[0].GetLineId(v));
        }
    }
    public override void Update()
    {
        base.Update();
        if (InputManager.Instance.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit(0);
        }
        if (InputManager.Instance.GetKeyDown(KeyCode.R))
        {
            if (frames != null)
            {
                frames.gameObject.SetActive(false);
            }
        //    player.ToFree();
            InstanceManager.Instance.Restart();
        }


        if (Player.Alive == false)
        {
            return;
        }
        if (player.IsFree == false)
        {
            OnNotFree();
        }
        else
        {

            if (InputManager.Instance.GetButtonDown("Interact"))
            {
                SetLayer();
            }

            if (InputManager.Instance.GetButtonUp("Interact"))
            {
                foreach (var x in GetInnerModule<InstanceInfo>().MapDic)
                {
                    {
                        x.Value.gameObject.layer = LayerMask.NameToLayer("Ground");
                    }
                }
                List<Collider2D> list = new List<Collider2D>();
                List<MeshComp> meshs = new List<MeshComp>();
                /*player.GetComponentInChildren<Collider2D>().OverlapCollider(new ContactFilter2D(), list);
                foreach (var x in list)
                {
                    if (x.GetComponent<MeshComp>().Tri.Type == player.TriData.Type)
                    {
                        meshs.Add(x.GetComponent<MeshComp>());
                    }
                }*/
                var dic = player.GetOverlap(player.TriData.Type);
                if (dic.Count > 0)
                {
                    TriData tr = null;
                    int cnt = -1;
                    foreach(var x in dic)
                    {
                        if (x.Value > cnt)
                        {
                            tr = x.Key;
                            cnt = x.Value;
                        }
                    }
                    if (cnt > 10)
                    {
                        player.ToTri(tr);

                    }
                }
                    /*
                if (meshs.Count > 0)
                {

                    meshs.Sort((MeshComp a, MeshComp b) =>
                    {
                        if (UnsafeTool.GetTwoAreaIntersection(a.Tri.ToWorld(a.transform).Points, player.TriData.ToWorld(player.transform).Points) <
                              UnsafeTool.GetTwoAreaIntersection(b.Tri.ToWorld(b.transform).Points, player.TriData.ToWorld(player.transform).Points)
                            )
                        {
                            return -1;
                        }
                        else
                        {
                            return 1;
                        }

                    })
                    player.ToTri(meshs[0].Tri);
                }*/

            }
        }
    }
}